﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using CoolCode.Linq;
using CoolCode.Services;
using System.Web.UI.WebControls;

namespace CoolCode.Web.UI
{
    public abstract class SearchPage<T, TService> : AuthPage, IFilterable<T>
        where TService : class, ISearchService<T>
    {
        private TService _Service;
        public virtual TService Service
        {
            get
            {
                if (_Service == null)
                {
                    _Service = ServiceFactory.Produce<TService>();
                }
                return _Service;
            }
        }

        protected virtual int PageSize { get { return 10; } }

        protected virtual bool AutoLoad { get { return true; } }

        #region IFilterable<T> Members

        public abstract IQueryBuilder<T> CreateFilter();

        #endregion

        private PaginatedList<T> _tempData ;
        public PaginatedList<T> ProvideData(PageParam p)
        {
            if (_tempData == null)
            {
                var qb = this.CreateFilter();
                var list = Service.Paging(qb, p);
                _tempData = list;
               // return list;
            }
            return _tempData;
        }

        public List<T> ProvideData()
        {
            var qb = this.CreateFilter();
            var list = Service.List(qb);
            return list;
        }

        public Action<int> Search;

        public void Setup(IButtonControl control, Action<SearchResponse<T>> success, Action<SearchFailResponse<T>> fail)
        {
            Action<int> search = ( pageIndex) =>
            {
                try
                {
                    var list = ProvideData(new PageParam(pageIndex, this.PageSize));
                    success(new SearchResponse<T>(list));
                }
                catch (Exception exp)
                {
                    fail(new SearchFailResponse<T>(null, exp));
                }
            };
            Search = search;
            control.Click += (sender, e) => search(0);

            if (AutoLoad)
            {
                if (!Page.IsPostBack)
                {
                    this.PreRender += (sender, e) => search(0);
                }
            }
        }

        public void Setup(IButtonControl control, IPager pager, Action<SearchResponse<T>> success, Action<SearchFailResponse<T>> fail)
        {
            //if (pager is IPartial<PaginatedList<T>>)
            //{
            //    IPartial<PaginatedList<T>> partial = (IPartial<PaginatedList<T>>)pager;

            //    Action<SearchResponse<T>> success2 = (response) =>
            //    {
            //        partial.Model = response.Result;
            //        partial.DataBind();
            //        success(response);
            //    };
            //    success = success2;
            //}

            this.Setup(control, success, fail);

            //Action<int> search = (pageIndex) =>
            //{
            //    try
            //    {
            //        var list = ProvideData(new PageParam(pageIndex, this.PageSize));
            //        success(new SearchResponse<T>(list));
            //    }
            //    catch (Exception exp)
            //    {
            //        fail(new SearchFailResponse<T>(null, exp));
            //    }
            //};
            pager.PageIndexChanging += (sender, e) => Search(e.NewPageIndex);
        }

        //public void Setup(IButtonControl control, IPartial<PaginatedList<T>> partial, Action<SearchResponse<T>> success, Action<SearchFailResponse<T>> fail)
        //{
        //    Action<SearchResponse<T>> success2 = (response) =>
        //    {
        //        partial.Model = response.Result;
        //        partial.DataBind();
        //        success(response);
        //    };

        //    this.Setup(control, success2, fail);
        //}


        public void Setup(IButtonControl control, IExportService<T> exportService,
            Action<ExportResponse> success, Action<ExportResponse> fail)
        {
            control.AsExportable(exportService, ProvideData, success, fail);
        }

        public void Setup(IExporter exporter, IExportService<T> exportService)
        {
            exporter.Setup(exportService, ProvideData);
        }
    }

    public class SearchResponse<T>
    {
        public PaginatedList<T> Result { get; private set; }

        public SearchResponse(PaginatedList<T> result)
        {
            this.Result = result;
        }
    }

    public class SearchFailResponse<T> : SearchResponse<T>
    {
        public Exception Exception { get; private set; }

        public SearchFailResponse(PaginatedList<T> result, Exception expection)
            : base(result)
        {
            this.Exception = expection;
        }
    }

    public interface IExporter
    {
        void Setup<T>(IExportService<T> exportService, Func<List<T>> provideData);
    }

    public abstract class SearchPage<TResult, TSearch, TService> : Page, IFilterable<TSearch>
       where TService : class, ISearchService<TResult, TSearch>
    {
        private TService _Service;
        public virtual TService Service
        {
            get
            {
                if (_Service == null)
                {
                    _Service = ServiceFactory.Produce<TService>();
                }
                return _Service;
            }
        }

        protected virtual int PageSize { get { return 10; } }

        protected virtual bool AutoLoad { get { return true; } }

        #region IFilterable<T> Members

        public abstract IQueryBuilder<TSearch> CreateFilter();

        #endregion

        private PaginatedList<TResult> _tempData;
        public PaginatedList<TResult> ProvideData(PageParam p)
        {
            if (_tempData == null)
            {
                var qb = this.CreateFilter();
                var list = Service.Paging(qb, p);
                _tempData = list;
                // return list;
            }
            return _tempData;
        }
 
        public void Setup(IButtonControl control, Action<SearchResponse<TResult>> success, Action<SearchFailResponse<TResult>> fail)
        {
            Action<int> search = (pageIndex) =>
            {
                try
                {
                    var list = ProvideData(new PageParam(pageIndex, this.PageSize));
                    success(new SearchResponse<TResult>(list));
                }
                catch (Exception exp)
                {
                    fail(new SearchFailResponse<TResult>(null, exp));
                }
            };

            control.Click += (sender, e) => search(0);

            if (AutoLoad)
            {
                if (!Page.IsPostBack)
                {
                    this.PreRender += (sender, e) => search(0);
                }
            }
        }

        public void Setup(IButtonControl control, IPager pager, Action<SearchResponse<TResult>> success, Action<SearchFailResponse<TResult>> fail)
        { 
            this.Setup(control, success, fail);

            Action<int> search = (pageIndex) =>
            {
                try
                {
                    var list = ProvideData(new PageParam(pageIndex, this.PageSize));
                    success(new SearchResponse<TResult>(list));
                }
                catch (Exception exp)
                {
                    fail(new SearchFailResponse<TResult>(null, exp));
                }
            };
            pager.PageIndexChanging += (sender, e) => search(e.NewPageIndex);
        }
    }

}
